package com.huayu.languo.common.configurer;

import com.huayu.languo.common.constant.AppConstants;
import com.huayu.languo.common.util.ExceptionUtil;
import com.huayu.languo.common.util.LogUtil;
import com.huayu.languo.model.dto.ResultDto;
import com.huayu.languo.model.enums.LogLevel;
import com.huayu.languo.model.enums.ResultCode;
import com.huayu.languo.model.excp.AbstractAppException;
import com.huayu.languo.model.excp.SystemException;
import org.apache.commons.lang3.StringUtils;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.ResponseStatus;

import javax.servlet.http.HttpServletRequest;


/**
 * @author 刘雄康
 * @version v1.0
 * @description 统一异常处理器
 * @date 2019年03月10日
 */
@ControllerAdvice
public class GlobalExceptionHandler {

    private static final String LOG_PATTERN = "errMsg[{}] costTime[{}] reqUrl[{}] reqMethod[{}] reqBody[{}] response[{}]";

    public GlobalExceptionHandler() {
        // Do nothing
    }


    @ResponseBody
    @ExceptionHandler(Exception.class)
    public ResultDto handleException(Exception e, HttpServletRequest request) {
        // 带@ResponseStatus 再次抛出
        if (null != AnnotationUtils.findAnnotation(e.getClass(), ResponseStatus.class)) {
            throw new SystemException(e);
        }

        ResultDto failureResponse = null;
        Exception et = null;
        String eMsg = e.getClass().getName().concat(AppConstants.DEFAULT_STR_END);
        // 空指针异常时，msg为null
        if (null != e.getMessage()) {
            eMsg = eMsg.concat(e.getMessage());
        }

        LogLevel logLevel = LogLevel.ERROR;
        if (e instanceof AbstractAppException && ((AbstractAppException) e).areBuzExp()) {
            AbstractAppException ex = (AbstractAppException) e;
            failureResponse = ResultDto.failure(ex.getResultCode(), ex.getData()).setMsg(ex.getMessage());
            if (StringUtils.isNotEmpty(ex.getDebugMessage())) {
                eMsg = e.getClass().getName().concat(AppConstants.DEFAULT_STR_END).concat(ex.getDebugMessage());
            }
            logLevel = ex.getLogLevel();
        } else if (ExceptionUtil.isHttpBindExp(e)) {
            String bindMsg = ExceptionUtil.getValidateMsg(e);
            failureResponse = ResultDto.failure(ResultCode.PARAMS_VALIDATE_412, null, bindMsg);
            logLevel = LogLevel.INFO;
        } else {
            failureResponse = ResultDto.failure(ResultCode.SERVER_ERROR_500);
            et = e;
        }

        Object[] getLogParams = {eMsg, LogUtil.getReqCostTime(), LogUtil.getReqUrl(request), request.getMethod(), LogUtil.getReqBody(request), failureResponse, et};
        ExceptionUtil.logExp(logLevel, LOG_PATTERN, getLogParams);
        return failureResponse;
    }
}
